package com.briup.client;

import com.briup.entity.Environment;
import com.briup.exception.CodeStatus;
import com.briup.exception.EnvException;
import com.briup.interfaces.Backup;
import com.briup.interfaces.Configuration;
import com.briup.interfaces.Gather;
import com.briup.interfaces.Log;
import org.w3c.dom.events.EventException;

import java.io.*;
import java.sql.Timestamp;
import java.util.*;

/**
 * 采集模块的实现类
 */
public class GatherImpl implements Gather {
    //读取数据清单地址
    private String srcFile;
    //维护日志对象
    private Log log;
    private Backup backup;

    public Collection<Environment> gather() throws EventException {
        Collection<Environment> list = new LinkedList<Environment>();
        File file = new File(srcFile);
        log.info("正在采集，采集的文件为" + file.getAbsolutePath());
        FileReader fr = null;
        BufferedReader br = null;

        int count1 = 0;
        int count2 = 0;
        int count3 = 0;
        try {
            //files1表示指针文件，里面储存了上次采集模块运行完读取到的文件的位置（指针）
            File file1 = new File("client/src/main/resources/index.txt");
            Long pNum = 0L;
            if (file1.exists()) {
                DataInputStream dis = new DataInputStream(new FileInputStream(file1));
                if (dis.available() > 0) {
                    pNum = dis.readLong();
                }
                dis.close();
            }
            if (!file.exists())
                return null;
            RandomAccessFile ramFile = new RandomAccessFile(file, "r");
            //如果读取到的指针大于文件的大小，这是错误的情况
            if (ramFile.length() < pNum) {
                DataOutputStream das = new DataOutputStream(new FileOutputStream(file1));
                das.writeLong(ramFile.length());
                das.close();
                ramFile.close();
                return null;
            }
            //如果文件的大小和指针的位置一样，那么就表示上次采集模块运行完后，
            //被采集的那个文件没有新增的数据，所以本次无需采集，直接返回null
            if (ramFile.length() == pNum) {
                ramFile.close();
                return null;
            }
            //如果文件的大小大于指针的位置，那么就表示上次采集模块运行完后，
            //被采集的那个文件有新增的数据，所以本次采集时通过seek方法设置指针为上次采集到的位置，
            //直接跳过之前已经读取过的数据
            ramFile.seek(pNum + 1);

            String line = null;
            while ((line = ramFile.readLine()) != null) {
                Environment environment = new Environment();
                String[] split = line.split("\\|");
                environment.setSrcId(split[0]);
                environment.setDesId(split[1]);
                environment.setDevId(split[2]);
                environment.setCount(Integer.parseInt(split[4]));
                environment.setCmd(split[5]);
                environment.setStatus(Integer.parseInt(split[7]));
                environment.setTime(new Timestamp(Long.parseLong(split[8])));
                //特殊部分
                String name = null;
                switch (split[3]) {
                    case "16":
                        count1++;
                        name = "温度";
                        environment.setName(name);
                        environment.setAddress(split[3]);
                        int v1 = Integer.parseInt(split[6].substring(0, 4), 16);
                        environment.setData((float) (v1 * 0.00268127 - 46.85));
                        //如果遇到温湿度，需拆开为两个对象
                        Environment e1 = new Environment();
                        e1.setSrcId(split[0]);
                        e1.setDesId(split[1]);
                        e1.setDevId(split[2]);
                        e1.setCount(Integer.parseInt(split[4]));
                        e1.setCmd(split[5]);
                        e1.setStatus(Integer.parseInt(split[7]));
                        e1.setTime(new Timestamp(Long.parseLong(split[8])));
                        name = "湿度";
                        e1.setName(name);
                        e1.setAddress(split[3]);
                        int v2 = Integer.parseInt(split[6].substring(4, 8), 16);
                        e1.setData((float) (v2 * 0.00190735 - 6));
                        list.add(e1);
                        break;
                    case "256":
                        count2++;
                        name = "CO2";
                        environment.setName(name);
                        environment.setAddress(split[3]);
                        //一个字节是2位十六进制，取前两个字节为数据
                        //二氧化碳浓度将16进制转换为10进制
                        String s1 = split[6].substring(0, 4);
                        float f = Integer.parseInt(s1, 16);
                        break;
                    case "1280":
                        count3++;
                        name = "光照强度";
                        environment.setName(name);
                        environment.setAddress(split[3]);
                        float f1 = Integer.parseInt(split[6].substring(0, 4), 16);
                        environment.setData(f1);
                        break;
                }
                list.add(environment);
            }

            long filePointer = ramFile.getFilePointer();
            DataOutputStream das = new DataOutputStream(new FileOutputStream("client/src/main/resources/index.txt"));
            //存储当前指针的位置到文件中
            das.writeLong(filePointer);
            das.close();
            log.info("指针数：" + filePointer);
        } catch (FileNotFoundException e) {
            log.error(e.getMessage());
            throw new EnvException(CodeStatus.FiLE_NOT_FOUND);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new EnvException(CodeStatus.IO_EXCEPTION);
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                    throw new EnvException(CodeStatus.IO_EXCEPTION);
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                    throw new EnvException(CodeStatus.IO_EXCEPTION);
                }
            }
        }
        //记录数据条数，分别种类是多少
        log.info("本次共采集：" + list.size() + "分别是：温度：" + count1 + "条 " + "湿度：" + count1 + "条 " + "二氧化碳浓度：" + count2 + "条 " + "光照强度" + count3 + "条");
        log.info("采集完成");

        try {
            backup.store("client/src/main/resources/beifen.txt", list, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("备份完成");
        return list;
    }

    @Override
    public void init(Properties properties) {
        srcFile = properties.getProperty("srcFile");
    }

    @Override
    public void setConfiguration(Configuration configuration) {
        log = configuration.getLog();
        backup = configuration.getBackup();
    }
}
